package alik.notes.client;

import alik.loginservice.shared.LoginInfo;
import alik.loginservice.shared.LoginService;
import alik.loginservice.shared.LoginServiceAsync;
import alik.loginservice.shared.exception.NotLoggedInException;
import alik.notes.client.event.Events;
import alik.notes.client.event.Events.NoteAddEvent;
import alik.notes.client.event.Events.NotesChangeEvent;
import alik.notes.client.event.impl.NoteAddHandlerImpl;
import alik.notes.client.event.impl.NotesChangeHandlerImpl;
import alik.notes.client.gin.AppGinInjectorFactory;
import alik.notes.shared.data.Note;
import alik.notes.shared.data.NoteBean;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class NotesEntryPoint implements EntryPoint {

	private static final int REFRESH_INTERVAL = 5000; // ms

	private LoginInfo loginInfo = null;

	private void loadLogin() {
		Window.open(loginInfo.getLoginUrl(), "_self", null);
	}

	private void handleError(Throwable error) {
		Window.alert(error.getMessage());
		if (error instanceof NotLoggedInException) {
			Window.Location.replace(loginInfo.getLogoutUrl());
		}
	}

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		LoginServiceAsync loginService = GWT.create(LoginService.class);
		loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}

			public void onSuccess(LoginInfo result) {
				loginInfo = result;
				if (loginInfo.isLoggedIn()) {
					loadNotes();
				} else {
					loadLogin();
				}
			}
		});

	}

	private void loadNotes() {
		Label welcomeLabel = new Label("Welcome " + loginInfo.getNickname() + ", Here is your list of notes:");
		Anchor signOutLink = new Anchor("(Sign Out)");
		signOutLink.setHref(loginInfo.getLogoutUrl());

		RootPanel.get(ElementId.welcomeText.name()).add(welcomeLabel);
		RootPanel.get(ElementId.signOutLink.name()).add(signOutLink);

		NotesTable notesTable = new NotesTable();
		RootPanel.get(ElementId.contentContainer.name()).add(notesTable);

		final Label titleLabel = new Label("Title:");
		titleLabel.setSize("100%", "100%");
		RootPanel.get(ElementId.titleLabelDiv.name()).add(titleLabel);

		final TextBox noteTitle = new TextBox();
		noteTitle.setSize("100%", "100%");
		RootPanel.get(ElementId.noteTitleTextBoxDiv.name()).add(noteTitle);

		noteTitle.setFocus(true);

		final TextArea noteDescription = new TextArea();
		noteDescription.setSize("100%", "100%");
		RootPanel.get(ElementId.noteDescTextAreaDiv.name()).add(noteDescription);

		final Label descLabel = new Label("Description:");
		descLabel.setSize("100%", "100%");
		RootPanel.get(ElementId.descLabelDiv.name()).add(descLabel);

		final Button addNoteButton = new Button("Add Note");
		addNoteButton.setStyleName(Style.addNoteButton.name());
		RootPanel.get(ElementId.actionContainer.name()).add(addNoteButton);

		addNoteButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Note note = new NoteBean(noteTitle.getText(), noteDescription.getText(), System.currentTimeMillis());
				AppGinInjectorFactory.GIN_INJECTOR.getEventBus().fireEvent(new Events.NoteAddEvent(note));
			}
		});

		AppGinInjectorFactory.GIN_INJECTOR.getEventBus().addHandler(NoteAddEvent.getType(), new NoteAddHandlerImpl());
		AppGinInjectorFactory.GIN_INJECTOR.getEventBus().addHandler(NotesChangeEvent.getType(), new NotesChangeHandlerImpl(notesTable));
		AppGinInjectorFactory.GIN_INJECTOR.getEventBus().fireEvent(new NotesChangeEvent());

		Timer refreshTimer = new Timer() {
			@Override
			public void run() {
				AppGinInjectorFactory.GIN_INJECTOR.getEventBus().fireEvent(new NotesChangeEvent());
			}
		};
		refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
	}
}